home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / misc / unix / unix_boot.lha / src / unix_boot.c < prev   
Encoding:
C/C++ Source or Header  |  1991-12-09  |  7.0 KB  |  253 lines

  1. /*
  2.  *  Original Code:
  3.  *  Copyright (C) 1991, Commodore Business Machines, Inc.
  4.  *
  5.  *  Assumes that copying code placed in chip ram is safe from being
  6.  *  overwritten.  Also makes some assumptions about the ELF kernel,
  7.  *  including assuming that the loadable, merged text and data segment
  8.  *  is the first program segment (the first program header table entry)
  9.  *  for fully linked kernels.
  10.  *
  11.  *  Uses bootmethod 3 (EXEC1):
  12.  *
  13.  *    D0 = 3                // boot method 3
  14.  *    D1 = (struct bootinfo *)    // pointer to boot information
  15.  *
  16.  *  91-12-10    mw    Converted original boot2.c file into a standalone
  17.  *            program runnable from AmigaDOS.
  18.  */
  19.  
  20. #include <exec/types.h>
  21. #include <exec/memory.h>
  22. #include <exec/nodes.h>
  23. #include <exec/libraries.h>
  24. #include <exec/io.h>
  25. #include <exec/execbase.h>
  26. #include <devices/trackdisk.h>
  27. #include <hardware/cia.h>
  28. #include <libraries/configregs.h>
  29. #include <libraries/configvars.h>
  30. #include <libraries/expansion.h>
  31. #include <libraries/expansionbase.h>
  32.  
  33. #include <inline/exec.h>
  34.  
  35. #define ABSEXECBASE ( (struct ExecBase **)4 )
  36.  
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <sys/elf.h>
  40. #include <stdio.h>
  41.  
  42. extern int errno;
  43.  
  44. /* I like even numbers ;-) */
  45. #define CHIP_BUF_SIZE 1024
  46.  
  47. #define reloc(adr) (adr)
  48.  
  49. #include "infoblock.h"
  50. #include "bootdata.h"
  51. #include "bootinfo.h"        /* NAUTO, etc */
  52.  
  53. #define min(a,b)    ((a)<(b)?(a):(b))
  54.  
  55. /*
  56.  *    Parameters to assembler "copyit" function.
  57.  */
  58.  
  59. struct copyinfo {
  60.     unsigned char *ci_loadbuf;
  61.     unsigned long ci_vaddr;
  62.     unsigned long ci_size;
  63.     unsigned long ci_entry;
  64.     unsigned long ci_d0;
  65.     unsigned long ci_d1;
  66.     unsigned long ci_copyit[1];    /* Code gets copied here */
  67. };
  68.  
  69.  
  70. int
  71. main (int argc, char *argv[])
  72. {
  73.     struct infoblock *infobuf;        /* Buffer for kernel info block */
  74.     unsigned long infobase;        /* Offset of kernel info block */
  75.     unsigned long filebase;        /* Offset of kernel on boot dev */
  76.     struct ExpansionBase *ExpansionBase;
  77.     struct bootinfo *bi;
  78.     struct BootData *bd;
  79.     struct ConfigDev *cdp;
  80.     struct ConfigDev *acp;
  81.     struct MemHeader *mhp;
  82.     struct MemHeader *mnp;
  83.     unsigned long nbytes;
  84.     unsigned long temp;
  85.     struct copyinfo *copyinfo;
  86.     Elf32_Addr bindaddr = 0xffffffff;
  87.     extern void copyit ();
  88.  
  89.     unsigned char *kernel_image, *chip_buf;
  90.     char *kernel_name = "unix";
  91.     int fd;
  92.     struct stat stb;
  93.  
  94.     
  95.     switch (argc)
  96.       {
  97.       case 3:
  98.     if (argv[2][0] == '$')
  99.       sscanf (argv[2], "$%x", &bindaddr);
  100.     else if (argv[2][0] == '0' &&
  101.              (argv[2][1] == 'x' || argv[2][1] == 'X'))
  102.       sscanf (argv[2]+2, "%x", &bindaddr);
  103.     else
  104.       sscanf (argv[2], "%d", &bindaddr);
  105.     /* fall into */
  106.  
  107.       case 2:
  108.         kernel_name = argv[1];
  109.     /* fall into */
  110.       
  111.       case 1:
  112.     break;
  113.  
  114.       default:
  115.         fprintf (stderr, "%s [kernel_file [bind_address]]\n", argv[0]);
  116.         return 20;
  117.       }
  118.  
  119.     if (stat (kernel_name, &stb) == -1)
  120.       {
  121.         fprintf (stderr, "%s: can't access %s, %s.\n",
  122.              argv[0], kernel_name, strerror (errno));
  123.     return 20;
  124.       }
  125.  
  126.     if (bindaddr <= 0x200000)
  127.       {
  128.         fprintf (stderr, "%s: can't bind into CHIP memory.\n", argv[0]);
  129.         return 20;
  130.       }
  131.  
  132.  
  133.     ExpansionBase = (struct ExpansionBase *) 
  134.             OpenLibrary (reloc (EXPANSIONNAME), 0);
  135.     if (ExpansionBase == NULL) 
  136.       {
  137.     fprintf (stderr, "%s: can't open expansion.library.\n", argv[0]);
  138.     return 20;
  139.       }
  140.  
  141.     chip_buf = AllocMem (CHIP_BUF_SIZE, MEMF_CHIP);
  142.     if (! chip_buf)
  143.       {
  144.         /* well.. if we can't get that much chip mem, displaying some 
  145.          * message probably won't work either, so quit quietly .. */
  146.         CloseLibrary (ExpansionBase);
  147.         return 20;
  148.       }
  149.  
  150.     /*
  151.      * Open the kernel file, and read it into a large enough buffer
  152.      */
  153.     kernel_image = AllocMem (stb.st_size, MEMF_FAST);
  154.     if (! kernel_image)
  155.       {
  156.         CloseLibrary (ExpansionBase);
  157.     FreeMem (chip_buf, CHIP_BUF_SIZE);
  158.         fprintf (stderr, "%s: out of memory loading kernel.\n", argv[0]);
  159.         return 20;
  160.       }
  161.     
  162.     if ((fd = open (kernel_name, 0)) < 0)
  163.       {
  164.     fprintf (stderr, "%s: can't open %s for read access, %s\n",        
  165.          argv[0], kernel_name, strerror (errno));
  166. shutup:
  167.         CloseLibrary (ExpansionBase);
  168.     FreeMem (chip_buf, CHIP_BUF_SIZE);
  169.     FreeMem (kernel_image, stb.st_size);
  170.     return 20;
  171.       }
  172.     
  173.     if (read (fd, kernel_image, stb.st_size) != stb.st_size)
  174.       {
  175.         fprintf (stderr, "%s: can't read %s, %s.\n",
  176.              argv[0], kernel_name, strerror (errno));
  177.         goto shutup;
  178.       }
  179.     close (fd);
  180.  
  181.     /*
  182.      *  Allocate space in chip memory to hold the bootinfo structure, and
  183.      *    then go through the various lists and initialize bootinfo.
  184.      */
  185.  
  186.     nbytes = sizeof (*bi);
  187.     bi = (struct bootinfo *) AllocMem (nbytes, MEMF_CLEAR | MEMF_CHIP);
  188.  
  189.     acp = bi -> autocon;
  190.     for (cdp = (struct ConfigDev *) ExpansionBase -> BoardList.lh_Head ;
  191.      cdp -> cd_Node.ln_Succ ;
  192.      cdp = (struct ConfigDev *) cdp -> cd_Node.ln_Succ) {
  193.     *acp++ = *cdp;
  194.     }
  195.  
  196.     mhp = bi -> memory;
  197.     for (mnp = (struct MemHeader *) (*ABSEXECBASE) -> MemList.lh_Head;
  198.      mnp -> mh_Node.ln_Succ;
  199.      mnp = (struct MemHeader *) mnp -> mh_Node.ln_Succ) 
  200.       {
  201.     *mhp = *mnp;
  202. #ifdef SUPERKICKSTART_KLUDGE    
  203.     /* this trick gets us the 512K back that are used as kick-`WORM' */
  204.     if (mhp->mh_Upper == (APTR)0x07f80000) mhp->mh_Upper = (APTR)0x08000000;
  205. #endif
  206.     mhp++;
  207.       }
  208.  
  209.     /*
  210.      *  Check to see if a specific binding address has been specified
  211.      *  in the info block.  A value of 0xFFFFFFFF indicates that the
  212.      *  boot code is to do automatic binding (the default) by scanning
  213.      *  the system's memory list and picking an appropriate relocation
  214.      *  address.
  215.      */
  216.  
  217.     if (bindaddr == 0xFFFFFFFF) bindaddr = bind ();
  218.  
  219.     /*
  220.      *  Do the relocation.  Note that for now, the text and data segments
  221.      *  must be contiguous in the relocatable ELF file, with text first.
  222.      *  This condition is tested for and enforced by this version.  At some
  223.      *  point, the information passed to the copyit() function needs to be
  224.      *  expanded to allow the text and data segments to occupy noncontiguous
  225.      *  memory prior to transfer to the final execution location by copyit().
  226.      */
  227.  
  228.     bd = &(bi -> bootdata);
  229.     rel (kernel_image, bindaddr, bd);
  230.     if ((bd -> bd_toffset + bd -> bd_tsize != bd -> bd_doffset)
  231.     || (bd -> bd_tvaddr + bd -> bd_tsize != bd -> bd_dvaddr)) {
  232.     fprintf (stderr, "%s: Text and data not contiguous!\n",
  233.          argv[0]);
  234.     goto shutup;
  235.     }
  236.  
  237.     /*
  238.      *    Initialize the copyinfo structure, copy the code for the copyit
  239.      *    function into chip memory, and then call the copy function in
  240.      *    supervisor mode.
  241.      */
  242.  
  243.     copyinfo = (struct copyinfo *) chip_buf;
  244.     copyinfo -> ci_loadbuf = kernel_image + bd -> bd_toffset;
  245.     copyinfo -> ci_vaddr   = bd -> bd_tvaddr;
  246.     copyinfo -> ci_size    = bd -> bd_tsize + bd -> bd_dsize;
  247.     copyinfo -> ci_entry   = bd -> bd_entry;
  248.     copyinfo -> ci_d0      = EXEC1;            /* boot method */
  249.     copyinfo -> ci_d1      = (unsigned long) bi;    /* bootinfo struct */
  250.     memcpy (copyinfo -> ci_copyit, reloc (copyit), TD_SECTOR);
  251.     return (supervisor (copyinfo -> ci_copyit, copyinfo));
  252. }
  253.